home *** CD-ROM | disk | FTP | other *** search
/ Aminet 33 / Aminet 33 - October 1999.iso / Aminet / util / misc / VMM_src.lha / VMM / forbidden_tasks.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-16  |  12.3 KB  |  491 lines

  1. #include <exec/types.h>
  2. #include "defs.h"
  3.  
  4. static char rcsid [] = "$Id: forbidden_tasks.c,v 3.5 95/12/16 18:36:49 Martin_Apel Exp $";
  5.  
  6. #define MIN(a,b) (((a)<(b))?(a):(b))
  7.  
  8. struct TaskNameEntry
  9.   {
  10.   struct MinNode TNE_Node;
  11.   char *TaskName;
  12.   ULONG MinPublic;
  13.   ULONG MinNonPublic;
  14.   BOOL SwapCode;
  15.   BOOL IsDir;
  16.   LONG LoadDir;        /* Only used if IsDir == TRUE */
  17.   };
  18.  
  19. #ifdef DEBUG
  20. ULONG HashTableUsage [HASHTABSIZE];
  21. #endif
  22.  
  23. PRIVATE struct List TaskInfo;
  24.  
  25. /**********************************************************************
  26.  * The index into the hash table is the lower six bits of the first
  27.  * character of the name
  28.  **********************************************************************/
  29.  
  30. PRIVATE void EnterIntoHashTab (char *name, int name_len,
  31.                                ULONG MinPublic, ULONG MinNonPublic)
  32. /* name_len is the length of the name excluding the trailing zero byte
  33.  * or the leading length byte for B-Strings.
  34.  */
  35. {
  36. static int next_free = -1;
  37. BOOL found = FALSE;
  38. struct HashEntry *HE;
  39. LONG offset;
  40.  
  41. offset = HASH_VAL ((ULONG)name);
  42.  
  43. PRINT_DEB ("EnterIntoHashTab: ", 0L);
  44. PRINT_DEB (name, 0L);
  45.  
  46. #ifdef DEBUG
  47. HashTableUsage [offset]++;
  48. #endif
  49.  
  50. Forbid ();
  51.  
  52. /* First check if it's already part of the hash table. Because the
  53.  * string is stored as an array of longwords, it might be that
  54.  * the bytes after the end of the string have changed. The longword
  55.  * approach is chosen for performance reasons in AllocMem. If it
  56.  * is found, copy the current string with the following bytes to the
  57.  * hash entry.
  58.  */
  59.  
  60. for (HE = HashTab [offset]; HE != NULL; HE = HE->NextEntry)
  61.   {
  62.   if (strncmp (name, (char*)HE->Name, name_len + 1) == 0)
  63.     {
  64.     PRINT_DEB ("Task already in hash table. Copying trailing bytes", 0L);
  65.     *(HE->Name + HE->NumLongsM1) = *((ULONG*)name + HE->NumLongsM1);
  66.     Permit ();
  67.     return;
  68.     }
  69.   }
  70.  
  71. /* The task has not been found in the hash table */
  72. while (!found)
  73.   {
  74.   next_free = (next_free + 1) % HASHTABSIZE;
  75.   HE = &(HashEntries [next_free]);
  76.   if (HE->Referenced)
  77.     {
  78.     HE->Referenced = FALSE;
  79.     PRINT_DEB ("EnterIntoHashTab: Marked entry as unused", 0L);
  80.     }
  81.   else
  82.     {
  83.     /* use this entry. First check if this entry was used before */
  84.     if (HE->Name != NULL)
  85.       {
  86.       /* it was used. Remove it from the corresponding hash chain. */
  87.       struct HashEntry **OldEntry;
  88.       int old_offset;
  89.  
  90.       PRINT_DEB ("EnterIntoHashTab: Evicting old hash table entry", 0L);
  91.  
  92.       old_offset = HE->HashIndex;
  93.       for (OldEntry = &(HashTab [old_offset]); *OldEntry != HE;
  94.            OldEntry = &((*OldEntry)->NextEntry))
  95.         PRINT_DEB ("Looping through old hash chain", 0L);
  96.  
  97.       *OldEntry = HE->NextEntry;
  98.  
  99.       FreeMem (HE->Name, (ULONG) (HE->NumLongsM1 + 1) * sizeof (ULONG));
  100.       }
  101.  
  102.     HE->MinPublic    = MinPublic;
  103.     HE->MinNonPublic = MinNonPublic;
  104.     HE->Referenced   = TRUE;
  105.     HE->HashIndex    = offset;
  106.  
  107.     /* name_len + 1 is either the length of a null-terminated string
  108.      * including the zero or the length of BCPL string including the
  109.      * leading size byte.
  110.      */
  111.     HE->NumLongsM1 = ALIGN_UP (name_len + 1, sizeof (ULONG)) / sizeof (ULONG) - 1;
  112.     if ((HE->Name = DoOrigAllocMem ((ULONG)(HE->NumLongsM1 + 1) * sizeof (ULONG),
  113.                                      MEMF_PUBLIC)) == NULL)
  114.       {
  115.       PRINT_DEB ("No space for hash table entry", 0L);
  116.       Permit ();
  117.       return;
  118.       }
  119.     CopyMem (name, HE->Name, (ULONG) (HE->NumLongsM1 + 1) * sizeof (ULONG));
  120.  
  121.     HE->NextEntry = HashTab [offset];
  122.     HashTab [offset] = HE;
  123.     found = TRUE;
  124.     }
  125.   }
  126. Permit ();
  127. }
  128.  
  129. /**********************************************************************
  130.  * This routine is called by the VM_Manager, for a task
  131.  * which does an AllocMem but hasn't found itself in the hash table.
  132.  **********************************************************************/
  133.  
  134. void ExtCheckVirtMem (struct Task *AskingTask)
  135.  
  136. {
  137. struct TaskNameEntry *TNE;
  138. struct Process *AskingProcess;
  139. char *name,         /* This is the one to be entered into the hash table */
  140.      *name_filepart;
  141. char complete_path [200];
  142. int name_len;
  143. BOOL IsCLI = FALSE;
  144.  
  145. AskingProcess = NULL;
  146.  
  147. PRINT_DEB ("ExtCheckVirtMem called for task", 0L);
  148.  
  149. if (AskingTask->tc_Node.ln_Type == NT_PROCESS)
  150.   {
  151.   AskingProcess = (struct Process*)AskingTask;
  152.   if (AskingProcess->pr_CLI != NULL)
  153.     {
  154.     struct CommandLineInterface *CLI;
  155.   
  156.     CLI = (struct CommandLineInterface*)BADDR(AskingProcess->pr_CLI);
  157.   
  158.     if (CLI->cli_CommandName != NULL)
  159.       {
  160.       name = (char*)BADDR(CLI->cli_CommandName);
  161.       if (*(name + 1) != 0)
  162.         {
  163.         name_len = (int)*name;
  164.         strncpy (complete_path, name + 1, (size_t)name_len);
  165.         complete_path [name_len] = 0;
  166.         name_filepart = FilePart (complete_path);
  167.         IsCLI = TRUE;
  168.         }
  169.       }
  170.     }
  171.   }
  172.  
  173. if (!IsCLI)
  174.   {
  175.   name = AskingTask->tc_Node.ln_Name;
  176.   name_filepart = name;
  177.   name_len = strlen (name);
  178.   }
  179.  
  180. PRINT_DEB (name_filepart, 0L);
  181.  
  182. for (TNE = (struct TaskNameEntry*)TaskInfo.lh_Head;
  183.      TNE->TNE_Node.mln_Succ != NULL; 
  184.      TNE = (struct TaskNameEntry*) TNE->TNE_Node.mln_Succ)
  185.   {
  186.   if (TNE->IsDir)
  187.     {
  188.     PRINT_DEB ("Checking directory", 0L);
  189.     if (AskingProcess != NULL)
  190.       {
  191.       PRINT_DEB ("TNE->LoadDir = %08lx", TNE->LoadDir);
  192.       PRINT_DEB ("HomeDir = %08lx", AskingProcess->pr_HomeDir);
  193.       if (SameLock (TNE->LoadDir, AskingProcess->pr_HomeDir) == LOCK_SAME)
  194.         {
  195.         PRINT_DEB ("File has been loaded from directory", 0L);
  196.         PRINT_DEB (TNE->TaskName, 0L);
  197.         EnterIntoHashTab (name, name_len, TNE->MinPublic, TNE->MinNonPublic);
  198.         return;
  199.         }
  200.       }
  201.     }
  202.   else  if (MatchPatternNoCase (TNE->TaskName, name_filepart))
  203.     {
  204.     /* Enter this task name into the hash table  */
  205.     EnterIntoHashTab (name, name_len, TNE->MinPublic, TNE->MinNonPublic);
  206.     return;
  207.     }
  208.   }
  209.  
  210. /* The task was not found in the TaskInfo list. Enter it into the hash table
  211.  * anyway and return the default value for allowance of virtual memory
  212.  */
  213.  
  214. PRINT_DEB ("Didn't find task in task info list", 0L);
  215. EnterIntoHashTab (name, name_len, CurrentConfig.DefaultMinPublic, 
  216.                   CurrentConfig.DefaultMinNonPublic);
  217. }
  218.  
  219. /**********************************************************************/
  220.  
  221. BOOL CodePagingAllowed (char *filename)
  222.  
  223. {
  224. struct TaskNameEntry *TNE;
  225. char *fp = FilePart (filename);
  226.  
  227. PRINT_DEB ("Checking code paging for file", 0L);
  228. PRINT_DEB (filename, 0L);
  229.  
  230. for (TNE = (struct TaskNameEntry*)TaskInfo.lh_Head;
  231.      TNE->TNE_Node.mln_Succ != NULL; 
  232.      TNE = (struct TaskNameEntry*) TNE->TNE_Node.mln_Succ)
  233.   {
  234.   if (TNE->IsDir)
  235.     {
  236.     LONG ProgLock,
  237.          ParentLock;
  238.  
  239.     ProgLock = Lock (filename, ACCESS_READ);
  240.     if (ProgLock != NULL)
  241.       {
  242.       ParentLock = ParentDir (ProgLock);
  243.       UnLock (ProgLock);
  244.       if (SameLock (TNE->LoadDir, ParentLock) == LOCK_SAME)
  245.         {
  246.         struct Process *LoadingProcess;
  247.         struct CommandLineInterface *CLI;
  248.  
  249.         PRINT_DEB ("File is in directory", 0L);
  250.         PRINT_DEB (TNE->TaskName, 0L);
  251.         UnLock (ParentLock);
  252.  
  253.         /* The name of the loaded file has to be entered into the hash table 
  254.          * because during loading virtual memory is allocated
  255.          * although the HomeDir of the process has not yet been set.
  256.          * Because the name is entered with a pointer to the original
  257.          * location, we hope that the CLI will have already set its name correctly.
  258.          * This would confuse ExtCheckVirtMem.
  259.          */
  260.  
  261.         LoadingProcess = (struct Process*) FindTask (NULL);
  262.         CLI = (struct CommandLineInterface*)BADDR (LoadingProcess->pr_CLI);
  263.         if (CLI != NULL && CLI->cli_CommandName != NULL)
  264.           {
  265.           char *name;
  266.           
  267.           name = (char*)BADDR (CLI->cli_CommandName);
  268.           if (*(name + 1) != 0)
  269.             EnterIntoHashTab (name, (int)*name, TNE->MinPublic, TNE->MinNonPublic);
  270.           }
  271.                         
  272.         return (TNE->SwapCode);
  273.         }
  274.       UnLock (ParentLock);
  275.       }
  276.     }
  277.   else if (MatchPatternNoCase (TNE->TaskName, fp))
  278.     {
  279.     return (TNE->SwapCode);
  280.     }
  281.   }
  282.  
  283. return (CurrentConfig.DefaultCodePaging);
  284. }
  285.  
  286. /**********************************************************************/
  287.  
  288. PRIVATE void FlushHashTable (void)
  289.  
  290. {
  291. int i;
  292. struct HashEntry *HE;
  293.  
  294. Forbid ();
  295. for (i = 0; i < HASHTABSIZE; i++)
  296.   {
  297.   HE = &(HashEntries [i]);
  298.   if (HE->Name != NULL)
  299.     {
  300.     FreeMem (HE->Name, (ULONG) (HE->NumLongsM1 + 1) * sizeof (ULONG));
  301.     HE->Name = NULL;
  302.     }
  303.   HashTab [i] = NULL;
  304.   }
  305. Permit ();
  306. }
  307.  
  308. /**********************************************************************/
  309.  
  310. int EnterTask (char *name, ULONG MinPublic, ULONG MinNonPublic, 
  311.                BOOL SwapCode, BOOL InsertFront)
  312.  
  313. {
  314. struct TaskNameEntry *NewEntry;
  315. char *token_buffer;
  316.  
  317. DISABLE_VM;
  318. if ((NewEntry = AllocVec ((ULONG)(sizeof (struct TaskNameEntry) + 2 * strlen (name) + 2),
  319.                          MEMF_PUBLIC)) == NULL)
  320.   {
  321.   ENABLE_VM;
  322.   PRINT_DEB ("EnterTask: Couldn't allocate mem for TaskNameEntry", 0L);
  323.   return (ERR_NOT_ENOUGH_MEM);
  324.   }
  325.  
  326. ENABLE_VM;
  327. token_buffer = (char*)(NewEntry + 1);
  328.  
  329. if (*(name + strlen (name) - 1) == '/' ||
  330.     *(name + strlen (name) - 1) == ':')
  331.   {
  332.   PRINT_DEB ("Entering directory", 0L);
  333.   PRINT_DEB (name, 0L);
  334.   NewEntry->IsDir = TRUE;
  335.   strcpy (token_buffer, name);
  336.   DISABLE_VM;
  337.   NewEntry->LoadDir = Lock (name, ACCESS_READ);
  338.   PRINT_DEB ("Lock is %lx", NewEntry->LoadDir);
  339.   ENABLE_VM;
  340.   }
  341. else
  342.   {
  343.   NewEntry->IsDir = FALSE;
  344.   ParsePatternNoCase (name, token_buffer, (LONG)(2 * strlen (name) + 2));
  345.   }
  346.  
  347. NewEntry->TaskName = token_buffer;
  348. NewEntry->MinPublic = MinPublic;
  349. NewEntry->MinNonPublic = MinNonPublic;
  350. NewEntry->SwapCode = SwapCode;
  351.  
  352. Forbid ();
  353. FlushHashTable ();
  354. if (InsertFront)
  355.   AddHead (&TaskInfo, (struct Node*)NewEntry);
  356. else
  357.   AddTail (&TaskInfo, (struct Node*)NewEntry);
  358.  
  359. Permit ();
  360. return (SUCCESS);
  361. }
  362.  
  363. /**********************************************************************/
  364.  
  365. BOOL RemoveTask (char *name)
  366.  
  367. {
  368. /* Removes a task from the task info list. If it is found, TRUE is returned,
  369.  * otherwise FALSE.
  370.  * Because the name itself is not stored in TaskNameEntry but only the parsed pattern,
  371.  * name is first parsed and then compared. This assumes that the parsed string is also
  372.  * terminated by a null byte.
  373.  */
  374.  
  375. struct TaskNameEntry *tmp;
  376. char token_buffer [200];
  377.  
  378. ParsePatternNoCase (name, token_buffer, 200L);
  379.  
  380. for (tmp = (struct TaskNameEntry *) TaskInfo.lh_Head; tmp->TNE_Node.mln_Succ != NULL;
  381.      tmp = (struct TaskNameEntry *) tmp->TNE_Node.mln_Succ)
  382.   {
  383.   if ((tmp->IsDir && strcmp (tmp->TaskName, name) == 0) ||
  384.       (!tmp->IsDir && (strcmp (tmp->TaskName, token_buffer) == 0)))
  385.     {
  386.     Forbid ();
  387.     Remove ((struct Node*)tmp);
  388.     FlushHashTable ();
  389.     Permit ();
  390.     if (tmp->IsDir)
  391.       {
  392.       PRINT_DEB ("Unlocking directory", 0L);
  393.       PRINT_DEB (tmp->TaskName, 0L);
  394.       DISABLE_VM;
  395.       UnLock (tmp->LoadDir);
  396.       ENABLE_VM;
  397.       }
  398.     return (TRUE);
  399.     }
  400.   }
  401.  
  402. return (FALSE);
  403. }
  404.  
  405. /**********************************************************************/
  406.  
  407. void NoMoreVM (void)
  408.  
  409. {
  410. /* Removes all entries from the hash table and the task table.
  411.  * It also sets DefaultVirtMem not to use VM anymore
  412.  */
  413.  
  414. struct TaskNameEntry *TNE;
  415.  
  416. PRINT_DEB ("NoMoreVM called", 0L);
  417. Forbid ();
  418. FlushHashTable ();
  419. while ((TNE = (struct TaskNameEntry*)RemHead (&TaskInfo)) != NULL)
  420.   {
  421.   if (TNE->IsDir)  
  422.     {
  423.     PRINT_DEB ("Unlocking directory", 0L);
  424.     PRINT_DEB (TNE->TaskName, 0L);
  425.     DISABLE_VM;
  426.     UnLock (TNE->LoadDir);
  427.     ENABLE_VM;
  428.     }
  429.   FreeVec (TNE);
  430.   }
  431.  
  432. CurrentConfig.DefaultMinPublic = USE_NEVER;
  433. CurrentConfig.DefaultMinNonPublic = USE_NEVER;
  434. Permit ();
  435. }
  436.  
  437. /**********************************************************************/
  438.  
  439. int InitTaskTable (void)
  440.  
  441. {
  442. int i;
  443.  
  444. NewList (&TaskInfo);
  445.  
  446. for (i = 0; i < HASHTABSIZE; i++)
  447.   {
  448.   HashTab [i] = NULL;
  449.   HashEntries [i].Name = NULL;
  450.   HashEntries [i].Referenced = FALSE;
  451.   }
  452.  
  453. return (SUCCESS);
  454. }
  455.  
  456. /**********************************************************************/
  457.  
  458. void KillTaskTable (void)
  459.  
  460. {
  461. struct TaskNameEntry *current;
  462.  
  463. if (TaskInfo.lh_Head == NULL)
  464.   return;
  465.  
  466. while ((current = (struct TaskNameEntry*)RemHead (&TaskInfo)) != NULL)
  467.   {
  468.   if (current->IsDir)  
  469.     {
  470.     PRINT_DEB ("Unlocking directory", 0L);
  471.     PRINT_DEB (current->TaskName, 0L);
  472.     UnLock (current->LoadDir);
  473.     }
  474.   FreeVec (current);
  475.   }
  476.  
  477. FlushHashTable ();
  478.  
  479. #ifdef DEBUG
  480.   {
  481.   ULONG i;
  482.  
  483.   for (i = 0; i < HASHTABSIZE; i++)
  484.     {
  485.     PRINT_DEB ("HashTable entry %ld", i);
  486.     PRINT_DEB ("was used %ld times", HashTableUsage [i]);
  487.     }
  488.   }
  489. #endif
  490. }
  491.